package net.oschina.bilbodai.common.retrofitor.def;

import okhttp3.Authenticator;
import okhttp3.Cache;
import okhttp3.CertificatePinner;
import okhttp3.ConnectionPool;
import okhttp3.ConnectionSpec;
import okhttp3.CookieJar;
import okhttp3.Dispatcher;
import okhttp3.Dns;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Protocol;

import javax.net.SocketFactory;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLSocketFactory;
import java.net.Proxy;
import java.net.ProxySelector;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author daimao  Date: 16/4/15 Time: 上午11:02
 * @version $Id$
 */
public class DefaultOkHttpClientFactory {
    private int connectTimeout = 10_000;
    private int readTimeout = 10_000;
    private int writeTimeout = 10_000;
    private boolean followSslRedirects = true;
    private boolean followRedirects = true;
    private boolean retryOnConnectionFailure = true;
    private int maxIdleConnections = 5;
    private long keepAliveMills = 5 * 60 * 1000; //5min
    private List<Interceptor> interceptors;
    private List<Interceptor> networkInterceptors;
    private Authenticator authenticator;
    private Cache cache;
    private ConnectionPool connectionPool;
    private Dns dns;
    private CookieJar cookieJar;
    private CertificatePinner certificatePinner;
    private List<ConnectionSpec> connectionSpecs;
    private Dispatcher dispatcher;
    private Proxy proxy;
    private List<Protocol> protocols;
    private ProxySelector proxySelector;
    private SocketFactory socketFactory;
    private SSLSocketFactory sslSocketFactory;
    private HostnameVerifier hostnameVerifier;
    private Authenticator proxyAuthenticator;

    public OkHttpClient create() {
        OkHttpClient.Builder builder = new OkHttpClient.Builder()
                .connectTimeout(getConnectTimeout(), TimeUnit.MILLISECONDS)
                .readTimeout(getReadTimeout(), TimeUnit.MILLISECONDS)
                .writeTimeout(getWriteTimeout(), TimeUnit.MILLISECONDS)
                .followRedirects(isFollowRedirects())
                .followSslRedirects(isFollowSslRedirects())
                .retryOnConnectionFailure(isRetryOnConnectionFailure())
                .connectionPool(new ConnectionPool(getMaxIdleConnections(), getKeepAliveMills(), TimeUnit.MILLISECONDS));
        if (interceptors != null && interceptors.size() > 0) {
            for (Interceptor interceptor : interceptors) {
                builder.addInterceptor(interceptor);
            }
        }
        if (networkInterceptors != null && networkInterceptors.size() > 0) {
            for (Interceptor networkInterceptor : networkInterceptors) {
                builder.addNetworkInterceptor(networkInterceptor);
            }
        }
        if (connectionSpecs != null && connectionSpecs.size() > 0) {
            builder.connectionSpecs(connectionSpecs);
        }
        if (protocols != null && protocols.size() > 0) {
            builder.protocols(protocols);
        }
        if (authenticator != null) {
            builder.authenticator(authenticator);
        }
        if (cache != null) {
            builder.cache(cache);
        }
        if (connectionPool != null) {
            builder.connectionPool(connectionPool);
        }
        if (dns != null) {
            builder.dns(dns);
        }
        if (cookieJar != null) {
            builder.cookieJar(cookieJar);
        }
        if (certificatePinner != null) {
            builder.certificatePinner(certificatePinner);
        }
        if (dispatcher != null) {
            builder.dispatcher(dispatcher);
        }
        if (proxy != null) {
            builder.proxy(proxy);
        }
        if (proxySelector != null) {
            builder.proxySelector(proxySelector);
        }
        if (socketFactory != null) {
            builder.socketFactory(socketFactory);
        }
        if (sslSocketFactory != null) {
            builder.sslSocketFactory(sslSocketFactory);
        }
        if (hostnameVerifier != null) {
            builder.hostnameVerifier(hostnameVerifier);
        }
        if (proxyAuthenticator != null) {
            builder.proxyAuthenticator(proxyAuthenticator);
        }
        return builder.build();
    }

    public List<Interceptor> getNetworkInterceptors() {
        return networkInterceptors;
    }

    public void setNetworkInterceptors(List<Interceptor> networkInterceptors) {
        this.networkInterceptors = networkInterceptors;
    }

    public Authenticator getAuthenticator() {
        return authenticator;
    }

    public void setAuthenticator(Authenticator authenticator) {
        this.authenticator = authenticator;
    }

    public Cache getCache() {
        return cache;
    }

    public void setCache(Cache cache) {
        this.cache = cache;
    }

    public ConnectionPool getConnectionPool() {
        return connectionPool;
    }

    public void setConnectionPool(ConnectionPool connectionPool) {
        this.connectionPool = connectionPool;
    }

    public Dns getDns() {
        return dns;
    }

    public void setDns(Dns dns) {
        this.dns = dns;
    }

    public CookieJar getCookieJar() {
        return cookieJar;
    }

    public void setCookieJar(CookieJar cookieJar) {
        this.cookieJar = cookieJar;
    }

    public CertificatePinner getCertificatePinner() {
        return certificatePinner;
    }

    public void setCertificatePinner(CertificatePinner certificatePinner) {
        this.certificatePinner = certificatePinner;
    }

    public List<ConnectionSpec> getConnectionSpecs() {
        return connectionSpecs;
    }

    public void setConnectionSpecs(List<ConnectionSpec> connectionSpecs) {
        this.connectionSpecs = connectionSpecs;
    }

    public Dispatcher getDispatcher() {
        return dispatcher;
    }

    public void setDispatcher(Dispatcher dispatcher) {
        this.dispatcher = dispatcher;
    }

    public Proxy getProxy() {
        return proxy;
    }

    public void setProxy(Proxy proxy) {
        this.proxy = proxy;
    }

    public List<Protocol> getProtocols() {
        return protocols;
    }

    public void setProtocols(List<Protocol> protocols) {
        this.protocols = protocols;
    }

    public ProxySelector getProxySelector() {
        return proxySelector;
    }

    public void setProxySelector(ProxySelector proxySelector) {
        this.proxySelector = proxySelector;
    }

    public SocketFactory getSocketFactory() {
        return socketFactory;
    }

    public void setSocketFactory(SocketFactory socketFactory) {
        this.socketFactory = socketFactory;
    }

    public SSLSocketFactory getSslSocketFactory() {
        return sslSocketFactory;
    }

    public void setSslSocketFactory(SSLSocketFactory sslSocketFactory) {
        this.sslSocketFactory = sslSocketFactory;
    }

    public HostnameVerifier getHostnameVerifier() {
        return hostnameVerifier;
    }

    public void setHostnameVerifier(HostnameVerifier hostnameVerifier) {
        this.hostnameVerifier = hostnameVerifier;
    }

    public Authenticator getProxyAuthenticator() {
        return proxyAuthenticator;
    }

    public void setProxyAuthenticator(Authenticator proxyAuthenticator) {
        this.proxyAuthenticator = proxyAuthenticator;
    }

    public List<Interceptor> getInterceptors() {
        return interceptors;
    }

    public void setInterceptors(List<Interceptor> interceptors) {
        this.interceptors = interceptors;
    }

    public boolean isFollowSslRedirects() {
        return followSslRedirects;
    }

    public void setFollowSslRedirects(boolean followSslRedirects) {
        this.followSslRedirects = followSslRedirects;
    }

    public boolean isFollowRedirects() {
        return followRedirects;
    }

    public void setFollowRedirects(boolean followRedirects) {
        this.followRedirects = followRedirects;
    }

    public boolean isRetryOnConnectionFailure() {
        return retryOnConnectionFailure;
    }

    public void setRetryOnConnectionFailure(boolean retryOnConnectionFailure) {
        this.retryOnConnectionFailure = retryOnConnectionFailure;
    }

    public int getMaxIdleConnections() {
        return maxIdleConnections;
    }

    public void setMaxIdleConnections(int maxIdleConnections) {
        this.maxIdleConnections = maxIdleConnections;
    }

    public long getKeepAliveMills() {
        return keepAliveMills;
    }

    public void setKeepAliveMills(long keepAliveMills) {
        this.keepAliveMills = keepAliveMills;
    }

    public int getConnectTimeout() {
        return connectTimeout;
    }

    public void setConnectTimeout(int connectTimeout) {
        this.connectTimeout = connectTimeout;
    }

    public int getReadTimeout() {
        return readTimeout;
    }

    public void setReadTimeout(int readTimeout) {
        this.readTimeout = readTimeout;
    }

    public int getWriteTimeout() {
        return writeTimeout;
    }

    public void setWriteTimeout(int writeTimeout) {
        this.writeTimeout = writeTimeout;
    }
}